package art.yulang.server;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * 自定义minicat4.0版本
 */
public class Bootstrap4 {
    /**自定义监听端口*/
    public static Integer DEFAULT_PORT = 8080;

    private Integer port;

    private String hostName;

    private String appBase;

//    private Mapper mapper;

    private Map<String, HttpServlet> servletMap = new HashMap<>();

    int corePoolSize = 5;
    int maximumPoolSize = 50;
    long keepAliveTime = 100;
    TimeUnit unit = TimeUnit.SECONDS;
    BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(50);
    ThreadFactory threadFactory = Executors.defaultThreadFactory();
    RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
    private ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);

    public void start() throws Exception {
        /**
         * 1、加载server.xml
         *      读取端口号、appBase等信息
         * 2、加载web.xml
         *      注册servlet
         */
        init();

//        ServerSocket serverSocket = new ServerSocket(port);
//        while (true){
//            Socket socket = serverSocket.accept();
//            RequestProcessor processor = new RequestProcessor(socket, servletMap);
//            threadPoolExecutor.execute(processor);
//        }
    }

    private void init() {
        /**
         * 加载minicat下的server.xml
         */
        loadServer();

        /**
         * 加载web.xml
         */
        loadServlet();
    }

    /**
     * 加载minicat下的server.xml文件
     *      初始化端口号、appBase等信息
     *
     * <server>
     *     <service>
     *         <Connector port="8080"/>
     *         <Engine>
     *             <Host name="localhost" appBase="H:/lagou-Java-high-18/projectes/webapps">
     *             </Host>
     *         </Engine>
     *     </service>
     * </server>
     */
    private void loadServer() {
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("server.xml");
        SAXReader reader = new SAXReader();
        try {
            Document document = reader.read(resourceAsStream);
            Element rootElement = document.getRootElement();
            List<Element> list = rootElement.selectNodes("//service");
            for (Element element : list) {
                //解析端口号
                Element connectorElement = (Element) element.selectSingleNode("Connector");
                if(null == connectorElement){
                    this.port = DEFAULT_PORT;
                }else {
                    String port = connectorElement.attributeValue("port");
                    this.port = Integer.parseInt(port);
                }

                //解析appBase
                Element hostElement = (Element) element.selectSingleNode("//Engine//Host");
                this.hostName = hostElement.attributeValue("name");
                this.appBase = hostElement.attributeValue("appBase");
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }

    /**
     * 加载web.xml：包括minicat下的web.xml以及webapps目录下个=各个项目的web.xml注册servlet信息
     */
    private void loadServlet() {
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("web.xml");
        SAXReader reader = new SAXReader();
        if(null != this.appBase){
            File appBaseFolder = new File(this.appBase);
            File[] files = appBaseFolder.listFiles();
            for (File file : files) {
                if(file.isDirectory()){
                    String name = file.getName();
                }
            }
        }else{
            loadServlet(resourceAsStream, reader);
        }
    }

    private void loadServlet(InputStream in, SAXReader reader){
        try {
            Document document= reader.read(in);
            Element rootElement = document.getRootElement();
            List<Element> list = rootElement.selectNodes("//servlet");
            for (Element element : list) {
                // <servlet-name>myServlet</servlet-name>
                Element servletNameElement = (Element) element.selectSingleNode("servlet-name");
                String servletName = servletNameElement.getStringValue();
                // <servlet-class>art.yulang.servlet.MyServlet</servlet-class>
                Element servletClassElement = (Element) element.selectSingleNode("servlet-class");
                String servletClass = servletClassElement.getStringValue();

                //根据servlet-name的值找到url-pattern
                Element servletMapping = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
                // <url-pattern>/myServlet</url-pattern>
                Element urlPatternElement = (Element) servletMapping.selectSingleNode("url-pattern");
                String urlPattern = urlPatternElement.getStringValue();

                servletMap.put(urlPattern, (HttpServlet) Class.forName(servletClass).newInstance());
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Bootstrap4 bootstrap = new Bootstrap4();
        try {
            bootstrap.start();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Integer getPort() {
        return port;
    }

    public void setPort(Integer port) {
        this.port = port;
    }

    public String getAppBase() {
        return appBase;
    }

    public void setAppBase(String appBase) {
        this.appBase = appBase;
    }

    public String getHostName() {
        return hostName;
    }

    public void setHostName(String hostName) {
        this.hostName = hostName;
    }

//    public Mapper getMapper() {
//        return mapper;
//    }
//
//    public void setMapper(Mapper mapper) {
//        this.mapper = mapper;
//    }
}
